﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media;

namespace QuantUtils
{
    using System.Reactive.Linq;
    using System.Windows.Controls;

    using ComboBox = System.Windows.Forms.ComboBox;
    using Control = System.Windows.Forms.Control;
    using Label = System.Windows.Forms.Label;
    using RichTextBox = System.Windows.Forms.RichTextBox;

    /// <remarks>   Olivier, 3/12/2012. </remarks>
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    public static class SafeInvoker
    {


        /// <summary>
        /// Gets the parent.
        /// </summary>
        /// <example>MainPage o = VisualTreeExtensions.GetParent(sender);
        ///            o.Content = new MyPage(); </example>
        /// <typeparam name="T"></typeparam>
        /// <param name="sender">The sender.</param>
        /// <returns></returns>
        public static T GetParent<T>(this object sender)
where T : class
        {
            FrameworkElement fe = sender as FrameworkElement;
            T acb = default(T);
            while (fe != null && acb == null)
            {
                fe = VisualTreeHelper.GetParent(fe) as FrameworkElement;
                acb = fe as T;
            }
            return acb;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// A Control extension method that safe invoke.
        /// Utility to avoid boiler-plate InvokeRequired code
        /// Usage: myCtrl.SafeInvoke(() =&gt; myCtrl.Enabled = false);
        /// </summary>
        /// <param name="ctrl">The ctrl to act on.</param>
        /// <param name="cmd">The command.</param>
        /// <remarks>
        /// Olivier, 3/12/2012.
        /// </remarks>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        public static void SafeInvoke(this Control ctrl, Action cmd)
        {
            if (ctrl.InvokeRequired)
                ctrl.BeginInvoke(cmd);
            else
                cmd();
        }

        //Replaces OnMyEventRaised boiler-plate code
        //Usage: this.RaiseEvent(myEventRaised);
        /// <summary>
        /// Raises the event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="evnt">The evnt.</param>
        public static void RaiseEvent(this object sender, EventHandler evnt)
        {
            var temp = evnt;
            if (temp != null)
                temp(sender, EventArgs.Empty);
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   An EventHandler extension method that raises an event. </summary>
        ///
        /// <remarks>   Olivier, 3/12/2012. </remarks>
        ///
        /// <param name="eventHandler"> The eventHandler to act on. </param>
        /// <param name="sender">       Source of the event. </param>
        /// <param name="e">            The T to process. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        public static void RaiseEvent(this EventHandler eventHandler, object sender, EventArgs e)
        {
            if (eventHandler != null)
                eventHandler(sender, e);
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   An EventHandler extension method that raises the event event. </summary>
        ///
        /// <remarks>   Olivier, 3/12/2012. </remarks>
        ///
        /// <typeparam name="T">    Generic type parameter. </typeparam>
        /// <param name="EVentHandlerT">    The EVentHandlerT to act on. </param>
        /// <param name="sender">           Source of the event. </param>
        /// <param name="e">                The T to process. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        public static void RaiseEvent<T>(this EventHandler<T> EVentHandlerT, object sender, T e)
            where T : EventArgs
        {
            if (EVentHandlerT != null)
                EVentHandlerT(sender, e);
        }



    }

    /// <summary>
    /// Various helpers for form updates and controls.
    /// </summary>
    public class FormHelper
    {

        /// <summary>
        /// Finds control embedded on searchControl.
        /// </summary>
        /// <param name="name">Name of the control.</param>
        /// <param name="searchControl">Control in which we're searching for control.</param>
        /// <returns>A value of null if no control has been found.</returns>
        internal static Control FindControl(string name, Control searchControl)
        {
            if (searchControl.Name == name)
            {
                return searchControl;
            }

            foreach (Control childControl in searchControl.Controls)
            {
                Control foundControl = FindControl(name, childControl);
                if (foundControl != null)
                {
                    return foundControl;
                }
            }

            return null;
        }

        /// <summary>
        /// Finds control of specified type embended on searchControl.
        /// </summary>
        /// <typeparam name="TControl">The type of the control.</typeparam>
        /// <param name="name">Name of the control.</param>
        /// <param name="searchControl">Control in which we're searching for control.</param>
        /// <returns>
        /// A value of null if no control has been found.
        /// </returns>
        internal static TControl FindControl<TControl>(string name, Control searchControl)
            where TControl : Control
        {
            if (searchControl.Name == name)
            {
                TControl foundControl = searchControl as TControl;
                if (foundControl != null)
                {
                    return foundControl;
                }
            }

            foreach (Control childControl in searchControl.Controls)
            {
                TControl foundControl = FindControl<TControl>(name, childControl);

                if (foundControl != null)
                {
                    return foundControl;
                }
            }

            return null;
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Safe invoker.
        /// Invoke any control events without raising UI Thread problems.			
        ///  </summary>

        public static Control FindControl<T>(Control.ControlCollection controlCollection)
        {
            foreach (Control child in controlCollection)
            {
                if (child.GetType() == typeof(T))
                {
                    return child;
                }
                else
                {
                    if (child.HasChildren)
                    {
                        return FindControl<ComboBox>(child.Controls);
                    }

                }
            }
            return null;
        }

        public class FormInvokes
        {
            private delegate void SetTextCallback(Control ctrl, string text);

            /// <summary>
            /// Sets the text on any control (where text can be set) and takes care of UI synchronizations
            /// </summary>
            /// <param name="ctrl">The CTRL.</param>
            /// <param name="text">The text.</param>
            public void SetText(Control ctrl, string text)
            {
                if (ctrl.InvokeRequired)
                {
                    ctrl.BeginInvoke(new SetTextCallback(SetText), ctrl, text);
                }
                else
                {
                    ctrl.Text = text;
                }
            }

            /// <summary>
            /// Appends text to a richbox control and takes care of the UI synchronization.
            /// </summary>
            /// <param name="ctrl">The CTRL.</param>
            /// <param name="text">The text.</param>
            public void RichBoxAppendText(Control ctrl, string text)
            {
                RichTextBox tx = ctrl as RichTextBox;
                if (tx != null)
                {
                    if (tx.InvokeRequired)
                    {
                        tx.BeginInvoke(new SetTextCallback(SetText), tx, text);
                    }
                    else
                    {
                        tx.AppendText(text);
                    }
                }
            }
        }
    }
}